package com.xinsoft.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.entity.dto.ExcelErrRowDTO;
import com.xinsoft.entity.dto.SysWarehouseItemImportDTO;
import com.xinsoft.entity.dto.SysWarehouseItemParam;
import com.xinsoft.entity.po.SysWarehouse;
import com.xinsoft.entity.po.SysWarehouseItem;
import com.xinsoft.mapper.SysWarehouseItemMapper;
import com.xinsoft.service.SysFileHisService;
import com.xinsoft.service.SysWarehouseItemService;
import com.xinsoft.service.SysWarehouseService;
import com.xinsoft.utils.ExcelUtils;
import com.xinsoft.validator.ValidatorUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lijie
 * @description 针对表【sys_warehouse_item(仓位)】的数据库操作Service实现
 * @createDate 2023-05-24 10:27:36
 */
@Service
public class SysWarehouseItemServiceImpl extends ServiceImpl<SysWarehouseItemMapper, SysWarehouseItem>
        implements SysWarehouseItemService {

    @Resource
    SysWarehouseItemMapper itemMapper;

    @Resource
    SysFileHisService sysFileHisService;

    @Resource
    SysWarehouseService sysWarehouseService;

    @Override
    public Object findPageListByParam(SysWarehouseItemParam param) {
        Page<SysWarehouseItem> page = new Page<SysWarehouseItem>(param.getCurrentPage(), param.getPageSize());
        LambdaQueryWrapper<SysWarehouseItem> queryWrapper = new LambdaQueryWrapper<>();
        //查询条件
        queryWrapper
                .eq(param.getWarehouseId() != null, SysWarehouseItem::getWarehouseId, param.getWarehouseId())
                .like(StrUtil.isNotBlank(param.getWhItemName()), SysWarehouseItem::getWhItemName, param.getWhItemName())
                .like(StrUtil.isNotBlank(param.getWhItemCode()), SysWarehouseItem::getWhItemCode, param.getWhItemCode());
        IPage<SysWarehouseItem> resultPage = itemMapper.selectPageInfo(page, queryWrapper);
        //返回值
        return resultPage;
    }

    @Override
    public JSONObject importExcel(MultipartFile multipartFile) throws IOException {
        // 初始化错误行信息list，用来记录导入失败的rowNum
        List<ExcelErrRowDTO> errRowDOs = new ArrayList<>();

        // 对excel是否为空进行check
        if (multipartFile.isEmpty()) {
            throw new BDException("导入失败，请选择文件！");
        }

        //设置excel参数
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        List<SysWarehouseItemImportDTO> sysWarehouseItemList;
        List<SysWarehouseItem> sysWarehouseItems = CollectionUtil.newArrayList();

        JSONObject result = new JSONObject();

        // 解析excel中的行，放到sysWarehouseItemList中
        try {
            // 解析excel
            sysWarehouseItemList = ExcelImportUtil.importExcel(multipartFile.getInputStream(), SysWarehouseItemImportDTO.class, params);
        } catch (Exception e) {
            throw new BDException("导入失败，文件内容解析错误！");
        }

        //校验
        if (sysWarehouseItemList.size() > 0) {
            //取出excel和db中所有重复的name
            List<String> excelWarehouseItemNames = sysWarehouseItemList.stream()
                    .map(SysWarehouseItemImportDTO::getWhItemName)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbWarehouseItemNames = this.getAllWarehouseName();//获取系统中所有的WarehouseItemName
            List<String> duplicateWarehouseItemNames = new ArrayList<>(); // 存放存在重复的warehouseItemName，用于定位重复存放存在重复的warehouseName的行

            if (dbWarehouseItemNames.size() > 0 && excelWarehouseItemNames.size() > 0) {
                dbWarehouseItemNames.addAll(duplicateWarehouseItemNames);//合并
                duplicateWarehouseItemNames = ExcelUtils.getDuplicateElements(duplicateWarehouseItemNames);//取出存在重复的username
            }

            //取出excel和db中所有重复的code
            List<String> excelWarehouseItemCodes = sysWarehouseItemList.stream()
                    .map(SysWarehouseItemImportDTO::getWhItemCode)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbWarehouseItemCodes = this.getAllWarehouseCode();//获取系统中所有的WarehouseItemCode
            List<String> duplicateWarehouseCodes = new ArrayList<>(); // 存放存在重复的WarehouseItemcode，用于定位重复存放存在重复的warehouseName的行

            if (dbWarehouseItemCodes.size() > 0 && excelWarehouseItemCodes.size() > 0) {
                dbWarehouseItemCodes.addAll(excelWarehouseItemCodes);//合并
                duplicateWarehouseCodes = ExcelUtils.getDuplicateElements(dbWarehouseItemCodes);//取出存在重复的username
            }

            // 仓库
            List<SysWarehouse> warehouseLise =  sysWarehouseService.list();
            Map<String, Integer> warehouseMap = warehouseLise.stream()
                    .collect(Collectors.toMap(SysWarehouse::getWarehouseName, SysWarehouse::getId, (v1, v2) -> v2));


            int index = 1;
            for (SysWarehouseItemImportDTO sysWarehouseItemDTO : sysWarehouseItemList) {
                index ++;
                // check
                StringBuilder stringBuilder = new StringBuilder();
                ExcelErrRowDTO excelErrRowDO= new ExcelErrRowDTO();

                // 参数校验
                stringBuilder.append(ValidatorUtils.validateExcel(sysWarehouseItemDTO));

                // 检验warehouseName 是否重复
                if(duplicateWarehouseItemNames.contains(sysWarehouseItemDTO.getWhItemName())){
                    stringBuilder.append("仓库名称已经存在，请勿重复！");
                }
                // 检验warehouseCode 是否重复
                if(duplicateWarehouseCodes.contains(sysWarehouseItemDTO.getWhItemCode())){
                    stringBuilder.append("仓库编号已经存在，请勿重复！");
                }

                // 仓库
                if(StringUtils.isNotEmpty(sysWarehouseItemDTO.getWarehouseName())){
                    Integer warehouseId = warehouseMap.get(sysWarehouseItemDTO.getWarehouseName());
                    if(warehouseId==null){
                        stringBuilder.append("仓库:"+sysWarehouseItemDTO.getWarehouseName()+",在系统中不存在");
                    }
                    sysWarehouseItemDTO.setWarehouseId(warehouseId);
                }

                // 将错误行信息保存到list
                String errMsg = stringBuilder.toString();
                if(StringUtils.isNotEmpty(errMsg)){
                    excelErrRowDO.setRowIndex(index);
                    excelErrRowDO.setErrMessage(errMsg);
                    errRowDOs.add(excelErrRowDO);
                    continue;
                }
                //保存
                SysWarehouseItem warehouseItem = new SysWarehouseItem();
                BeanUtils.copyProperties(warehouseItem,warehouseItem);
                sysWarehouseItems.add(warehouseItem);
            }
            saveBatch(sysWarehouseItems);

            // 导出错误行
            String errFileUrl = ExcelUtils.exportErrRows(errRowDOs,multipartFile,sysFileHisService);
            result.put("errFileUrl",errFileUrl);
        }
        return result;
    }

    @Override
    public void insertOrUpdateBatch(List<SysWarehouseItem> sysWarehouseItemList) {
        baseMapper.insertOrUpdateBatch(sysWarehouseItemList);
    }

    @Override
    public int batchDelete(Map<String, Object> map) {
        return baseMapper.batchDelete(map);
    }
    @Override
    public int allDelete() {
        return baseMapper.allDelete();
    }

    private List<String> getAllWarehouseName() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("wh_item_name");
        List<SysWarehouseItem> userList = this.list();
        List<String> names = userList.stream().map(SysWarehouseItem::getWhItemName).collect(Collectors.toList());
        return names;
    }

    private List<String> getAllWarehouseCode() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("wh_item_code");
        List<SysWarehouseItem> userList = this.list();
        List<String> codes = userList.stream().map(SysWarehouseItem::getWhItemCode).collect(Collectors.toList());
        return codes;
    }
}




